function [] = plotstructpar(t, par, fieldTitles, fieldUnits, fieldUnitConvertCoef, parLegends, varargin)
%PLOTSTRUCTPAR 绘制结构体形式的参数曲线
%
% Tips:
% 1. 各组参数由线宽区分，每组参数中的各个域占用不同的子绘图，每个域中的不同行、列首先由颜色区分，然后由线形区分
%
% Input Arguments:
% t: 向量或元胞向量，时间，当为向量时，为par的各组参数的时刻（此时par各组参数最后一维尺寸相同），当为元胞向量时，各元素为向量，对应par的各组参数的时刻（此时par各组参数最后一维尺寸可不同），单位s
% par: 结构体（当t为向量时）或结构体向量（当t为元胞向量时，这时结构体向量的每个元素为一组参数）形式的参数，结构体的各个域为2维或3维数组，与对应的t长度相等，时间沿最后一维变化
% fieldTitles: 包含par所有域的结构体，各域为字符串，对应par各域的标题
% fieldUnits: 包含par所有域的结构体，各域为字符串，对应par各域的单位
% fieldUnitConvertCoef: 包含par所有域的结构体，各域为双精度浮点数，对应par各域的单位转换系数
% parLegends: 包含par所有域的结构体或结构体向量，各域为列元胞向量（当par对应域为2维数组时）或2维元胞数组（当par对应域为3维数组时），各元素为字符串，对应各参数的图例
% # varargin: 包含以下“参数-数值”对：
%     fieldPlotMask: 包含par所有域的结构体，各域为逻辑列向量（当par对应域为2维数组时）或2维数组（当par对应域为3维数组时），true表示绘制对应参数的曲线，false表示不绘制，空表示绘制所有参数
%     tSects: 向量，绘制时间分隔线的时间点，单位s
%     figName: 字符串，绘图的名称，默认为空
%     tUnit: 字符串，t的单位，默认为's'
%     marker: 字符串，绘图的点型，默认为'none'
%     hFig: 标量，绘图的句柄，若不输入将新建绘图
%     m, n: 标量，subplot的行、列数，若有一项不输入将根据需要绘制的域的个数按均匀分布原则自动确定
%     p: 标量，第一幅曲线在subplot中的起始位置，若不输入将默认为1，为1时将清空hFig指定的绘图
%
% NOTE: 本函数使用线性索引

ps = inputParser;
ps.FunctionName = 'plotstructpar';
addRequired(ps, 't', @(x)(isnumeric(x)||iscell(x)));
addRequired(ps, 'par', @isstruct);
addRequired(ps, 'fieldTitles', @isstruct);
addRequired(ps, 'fieldUnits', @isstruct);
addRequired(ps, 'fieldUnitConvertCoef', @isstruct);
addRequired(ps, 'parLegends', @isstruct);
addParameter(ps, 'fieldPlotMask', [], @(x)(isstruct(x)||isempty(x)));
addParameter(ps, 'tSects', [], @isnumeric);
addParameter(ps, 'figName', [], @ischar);
addParameter(ps, 'tUnit', 's', @ischar);
addParameter(ps, 'marker', 'none', @ischar);
addParameter(ps, 'hFig', [], @isnumeric);
addParameter(ps, 'm', 0, @isnumeric);
addParameter(ps, 'n', 0, @isnumeric);
addParameter(ps, 'p', 1, @isnumeric);
parse(ps, t, par, fieldTitles, fieldUnits, fieldUnitConvertCoef, parLegends, varargin{:});

fieldPlotMask = ps.Results.fieldPlotMask;
tSects = ps.Results.tSects;
figName = ps.Results.figName;
tUnit = ps.Results.tUnit;
marker = ps.Results.marker;
hFig = ps.Results.hFig;
m = ps.Results.m;
n = ps.Results.n;
p = ps.Results.p;

% 创建绘图
preparefig(figName, hFig, p==1);

% 统计需要绘制的参数类型数并确定subplot行列数
fieldNames = fieldnames(par);
if ~isempty(fieldPlotMask)
    plotTypeSum = 0;
    for iField=1:length(fieldNames)
        if any(any(fieldPlotMask.(fieldNames{iField})))
            plotTypeSum = plotTypeSum + 1;
        end
    end
else
    plotTypeSum = length(fieldNames);
end
if (m==0) || (n==0)
    [m, n] = roundsqrt(plotTypeSum);
end

% 处理时间
if iscell(t)
    for i=1:length(t)
        tTest = t{i}(~isnan(t{i}));
        if ~isequal(tTest, unique(tTest)) || ~issorted(tTest)
            warning('plotstructpar:timedisorder', ['t{' int2str(i) '} is not unique or not sorted.']);
        end
    end
else
    tTest = t(~isnan(t));
    if ~isequal(tTest, unique(tTest)) || ~issorted(tTest)
        warning('plotstructpar:timedisorder', 't is not unique or not sorted.');
    end
    t = repmat({t}, size(par));
end
tMin = Inf;
tMax = -Inf;
for i=1:length(t)
    tMin = min(min(t{i}(:)), tMin);
    tMax = max(max(t{i}(:)), tMax);
end

% 绘制参数
colorSpecs = {'b', 'g', 'r', 'c', 'm', 'y', 'k'};
colorSpecsLen = length(colorSpecs);
lineStyles = {'-', '--', ':', '-.'};
lineStylesLen = length(lineStyles);
for iField=1:length(fieldNames)
    if isempty(fieldPlotMask) || any(any(fieldPlotMask.(fieldNames{iField})))
        % 绘制一个域内的参数
        subplot(m, n, p);
        sz = size(par(1).(fieldNames{iField}));
        if ismatrix(par(1).(fieldNames{iField}))
            for iPar = 1:length(par)
                % 绘制一组参数
                for iDim=1:sz(1, 1)
                    % 绘制单个参数
                    if isempty(fieldPlotMask) || fieldPlotMask.(fieldNames{iField})(iDim, 1)
                        plot(t{iPar}, par(iPar).(fieldNames{iField})(iDim, :)*fieldUnitConvertCoef.(fieldNames{iField}), ...
                            'DisplayName', parLegends(iPar).(fieldNames{iField}){iDim, 1}, 'Color', colorSpecs{1, mod(iDim-1, colorSpecsLen)+1}, ...
                            'LineWidth', iPar, 'Marker', marker);
                        hold on;
                    end
                end
            end
        elseif ndims(par(1).(fieldNames{iField})) == 3
            for iPar = 1:length(par)
                % 绘制一组参数
                for iDim=1:sz(1, 1)
                    % 绘制单个参数
                    for iDim2=1:sz(1, 2)
                        if isempty(fieldPlotMask) || fieldPlotMask.(fieldNames{iField})(iDim, iDim2)
                            plot(t{iPar}, squeeze(par(iPar).(fieldNames{iField})(iDim, iDim2, :))*fieldUnitConvertCoef.(fieldNames{iField}), ...
                                'DisplayName', parLegends(iPar).(fieldNames{iField}){iDim, iDim2}, 'Color', colorSpecs{1, mod(iDim2-1, colorSpecsLen)+1}, ...
                                'LineStyle', lineStyles{1, mod(iDim-1, lineStylesLen)+1}, 'LineWidth', iPar, 'Marker', marker);
                            hold on;
                        end
                    end
                end
            end
        else
            warning('plotsenstriadpar:invalidParDim', 'Invalid parameter number of dimensions, should be 2 or 3.');
        end
        % 绘制时间分隔线
        xperplines_ylim(tSects, tMax, tMin);
        % 绘制辅助信息
        title(fieldTitles.(fieldNames{iField}));
        xlabel(['t(' tUnit ')']);
        ylabel(['(' fieldUnits.(fieldNames{iField}) ')']);
        legend('show', 'Location', 'Best');
        grid on;
        hold off;
        p = p + 1;
    end
end
end